package com.qf.simple;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer1 {
    public static void main(String[] args) throws IOException, TimeoutException {
        //① 创建一个连接工厂对象
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("cdm");

        //② 利用连接工厂获取一个连接对象
        Connection connection = factory.newConnection();

        //③ 利用连接对象获取一个channel对象
        Channel channel = connection.createChannel();

        //④ 消费消息
        /*
            String queue: 要消费的队列名称
            boolean autoAck ：是否自动提交，true,自动提交，一旦提交，消息就认为消费成功，从mq中删除,false，需要根据业务执行的情况，决定是否提交
            Consumer callback：消费消息的回调
         */
        channel.basicConsume("cdm.simple", false, new DefaultConsumer(channel){
            /*
                String consumerTag:消费者标记，一个消费者对应一个，不变
                Envelope envelope:包含了消息的交换机、路由键等信息
                AMQP.BasicProperties properties:消息属性.消息的唯一标识、消息超时时间、消息是否持久化
                byte[] body: 消息内容
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                long deliveryTag = envelope.getDeliveryTag();
                try {
                    System.out.println("消费者标记:" + consumerTag);
//                String exchange = envelope.getExchange();
//                String routingKey = envelope.getRoutingKey();

                    System.out.println("msg:" + new String(body,"utf-8"));

                    //模拟异常,演示非正常消费
                    int i = 1/0;

                    //根据处理业务的结果，执行提交或者不提交 -- 成功，提交
                    /*
                        deliveryTag: 发送端的唯一标识，每个发送端不同，不变
                        multiple:是否批量确认，如果这个发送端，之前还有未被确认的消息，如果设置为true，会将之前没被确认的一并确认。如果设置为false，只会确定当前消费到的这一条
                     */
                    getChannel().basicAck(deliveryTag,false);
                }catch (Exception e){
                    //根据处理业务的结果，执行提交或者不提交 -- 失败，不提交
                    /*
                        deliveryTag: 发送端的唯一标识，每个发送端不同，不变
                        multiple:是否批量确认，如果这个发送端，之前还有未被确认的消息，如果设置为true，会将之前没被确认的一并确认。如果设置为false，只会确定当前消费到的这一条
                        requeue: 是否重新入队，如果为true，会重新进入队列，被再次消费（重试）,如果为false，直接丢弃消息
                                实际业务中，给true，但是会记录重试的次数（redis），达到次数，会将消息存入数据库的重试表，会利用定时任务，去重试表中进行重试处理，设置false
                     */
                    getChannel().basicNack(deliveryTag,false,false);
                }


            }
        });
    }
}
